/******************************************************
* Team WB
* Brett Cate, William Kim
* 
* Main file for testing SC2 simulator
*******************************************************/


#include "registerFile.h"

/*
Creates a new register file, containing 16 register pointers in an array.

return value: A pointer to an array of 16 registers.
*/
RegisterFilePtr registerFile_new() {
	RegisterFilePtr regFilePtr = (RegisterFilePtr) malloc(sizeof(RegisterPtr) * REGISTER_COUNT);
	int i = 0;
	for (i = 0; i < REGISTER_COUNT; i++) {
		regFilePtr[i] = register_new(); 
	}
	return regFilePtr;
}


/*
Returns the selected byte from the given register.

parameter (the_register_file): The register file whose register the byte comes from.
parameter (the_register_number): The register number for the register whose byte is returned.
parameter (the_selected_byte): The number of the byte to return from the register. 
Either 1 (high byte) or 0 (low byte).

parameter (*the_error): Pointer to the int value of the error code for this function.

return value: A uchar containing the value of the byte chosen in the selected register.

*/
uchar registerFile_getByteFrom(RegisterFilePtr the_register_file, int the_register_number, int the_selected_byte, int* the_error) {
	*the_error = NO_ERROR;
	if (the_register_file == NULL) {
		*the_error = NULL_POINTER_ERROR;
		return 0;
	}
	if (the_register_number >= REGISTER_COUNT || the_register_number < 0) {
		*the_error = INVALID_REG_NUM;
		return 0;
	}
	if (the_selected_byte != LOW_BYTE && the_selected_byte != HIGH_BYTE) {
		*the_error = INVALID_BYTE_NUM;
		return 0;
	}

	if (the_selected_byte == HIGH_BYTE) {
		return register_getHIByte(the_register_file[the_register_number], the_error);
	} else {
		assert (the_selected_byte == LOW_BYTE);
		return register_getLowByte(the_register_file[the_register_number], the_error);
	}
}


/*
Puts the given byte into the register indicated in the given register file, 
and returns the int value of the error code for this function.

parameter (the_register_file): The register file into whose register the byte is put.
parameter (the_register_number): The number of the register where the byte is put.
parameter (the_selected_byte): The number of the byte, either 1 for high order or 0 for 
low order, where the given value is placed.

parameter (the_byte): The value to put in the indicated register.

return value: The int value of the error code for this function.
*/
int registerFile_putByteTo(RegisterFilePtr the_register_file, int the_register_number, int the_selected_byte, uchar the_byte) {
	if (the_register_file == NULL) {
		return NULL_POINTER_ERROR;
	}
	if (the_register_number >= REGISTER_COUNT || the_register_number < 0) {
		return INVALID_REG_NUM;
	}
	if (the_selected_byte != LOW_BYTE && the_selected_byte != HIGH_BYTE) {
		return INVALID_BYTE_NUM;
	}

	if (the_selected_byte == HIGH_BYTE) {
		return register_putHIByte(the_register_file[the_register_number], the_byte);
	} else {
		assert (the_selected_byte == LOW_BYTE);
		return register_putLowByte(the_register_file[the_register_number], the_byte);
	}
}


/*
Returns the value of the indicated register in the given register file.

parameter (the_register_file): The register file whose register value is returned.
parameter (the_register_number): The number of the register whose value is returned.
parameter (*the_error): Pointer to the int value of the error code for this function.

return value: A ushort containing the value of the indicated register in the given register file.
*/
ushort registerFile_getRegValue(RegisterFilePtr the_register_file, int the_register_number, int* the_error) {
	*the_error = NO_ERROR;
	if (the_register_file == NULL) {
		*the_error = NULL_POINTER_ERROR;
		return 0;
	}
	if (the_register_number >= REGISTER_COUNT || the_register_number < 0) {
		*the_error = INVALID_REG_NUM;
		return 0;
	}
	return register_getRegValue(the_register_file[the_register_number], the_error);
}


/*
Puts the given value into the indicated register of the given register file and 
returns the int value of the error code for this function.

parameter (the_register_file): The register file into whose register the value is put.
parameter (the_register_number): The number of the register whose value is changed.
parameter (the_value): The value which is put into the indicated register.

return value: The int value of the error code for this function.
*/
int registerFile_putRegValue(RegisterFilePtr the_register_file, int the_register_number, ushort the_value) {
		if (the_register_file == NULL) {
		return NULL_POINTER_ERROR;
	}
	if (the_register_number >= REGISTER_COUNT || the_register_number < 0) {
		return INVALID_REG_NUM;
	}
	return register_putRegValue(the_register_file[the_register_number], the_value);
}

/* End Program */
